//
//  WKBleManager.m
//  ourToken
//
//  Created by wakeup on 2018/6/14.
//  Copyright © 2018年 ourtoken. All rights reserved.
//

#import "WKBleManager.h"

//正常使用时的UUID
#define oServiceUUID     @"6e400001-b5a3-f393-e0a9-e50e24dcca9e"
#define oWriteUUID       @"6e400002-b5a3-f393-e0a9-e50e24dcca9e"
#define oNotifyUUID      @"6e400003-b5a3-f393-e0a9-e50e24dcca9e"

//进入ISP模式后使用的UUID
#define hServiceUUID     @"00001234-0000-1000-8000-00805f9b34fb"
#define hWriteUUID       @"ff02"
#define hNotifyUUID      @"ff04"
#define resetUUID        @"ff01"

//UUID变量
static NSString *ServiceUUID = @"";
static NSString *WriteUUID = @"";
static NSString *NotifyUUID = @"";

@interface WKBleManager ()<CBCentralManagerDelegate, CBPeripheralDelegate>

//升级时使用
@property (nonatomic,strong)CBCharacteristic *fileService;
@property (nonatomic,strong)CBCharacteristic *resetService;

//用来判断是否进行数据拼接
@property (nonatomic, assign) BOOL combine;

//拼接数据的总长度
@property (nonatomic, assign) int combineSize;

//拼接的数据
@property (nonatomic, strong) NSMutableData *combineData;

@end

@implementation WKBleManager

#pragma mark - 初始化
+ (WKBleManager *)sharedBleManager {
    static WKBleManager *bleManager;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        bleManager = [[self alloc] init];
    });
    return bleManager;
}

- (instancetype)init
{
    self = [super init];
    if (self) {
        self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
        self.peripheralArray = [[NSMutableArray alloc] init];
        self.bleArray = [[NSMutableArray alloc] init];
        self.combineData = [[NSMutableData alloc] init];
    }
    return self;
}

#pragma mark - 开始搜索设备
- (void)startFindBleDevices {
    NSDictionary *dictionary = @{CBCentralManagerScanOptionAllowDuplicatesKey:@(YES)};
    [self.centralManager scanForPeripheralsWithServices:nil options:dictionary];
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [bleSelf stopFindBleDevices];
    });
}

#pragma mark - 停止搜索设备
- (void)stopFindBleDevices {
    [self.centralManager stopScan];
}

#pragma mark - 连接设备
- (void)connectBleDevice:(CBPeripheral *)peripheral {
    
    if ([peripheral.name isEqualToString:@"Huntersun-BLE"]) {
        ServiceUUID = hServiceUUID;
        WriteUUID = hWriteUUID;
        NotifyUUID = hNotifyUUID;
    }
    else {
        ServiceUUID = oServiceUUID;
        WriteUUID = oWriteUUID;
        NotifyUUID = oNotifyUUID;
    }
    
    [self.centralManager stopScan];
    self.activePeripheral = peripheral;
    [self.centralManager connectPeripheral:peripheral options:nil];
}

#pragma mark - 断开设备
- (void)disconnectBleDevice:(CBPeripheral *)peripheral {
    [self.centralManager cancelPeripheralConnection:peripheral];
}

#pragma mark - CBCentralManagerDelegate
#pragma  mark - 检测是否打开蓝牙
- (void) centralManagerDidUpdateState:(CBCentralManager *)centralManager {
    if (centralManager.state == CBCentralManagerStatePoweredOn) {
        self.on = YES;
        [[NSNotificationCenter defaultCenter] postNotificationName:kTag_Phone_Ble_On object:nil];
    }
    else {
        self.on = NO;
        [[NSNotificationCenter defaultCenter] postNotificationName:kTag_Phone_Ble_Off object:nil];
    }
}

/*
 peripheral：扫描到的周边设备
 advertisementData：响应数据  跟广播包所放的内容有关系
 RSSI即Received Signal Strength Indication：接收的信号强度指示
 */
#pragma mark - 搜索到的设备
- (void) centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI {
    
    DLog(@"广播蓝牙名:%@  信号:%@  advertisementData:%@", peripheral.name, RSSI,  advertisementData);
    
    if ([RSSI intValue] == 127) {
        return;
    }
    
    NSString *name = advertisementData[CBAdvertisementDataLocalNameKey];
    if ((peripheral.name.length == 0) || (name.length == 0)) {
        return;
    }
    
    if (![_peripheralArray containsObject:peripheral]) {
        [_peripheralArray addObject:peripheral];
        
        NSData *tempMac = [advertisementData objectForKey:@"kCBAdvDataManufacturerData"];
        uint8_t dataVal[100] = {0x0};
        [tempMac getBytes:&dataVal length:tempMac.length];
        
        WKBleModel *model = [[WKBleModel alloc] init];
        if (tempMac.length == 8) {
            NSString *mac = [[NSString stringWithFormat:@"%02x:%02x:%02x:%02x:%02x:%02x",dataVal[2],dataVal[3],dataVal[4],dataVal[5],dataVal[6],dataVal[7]] lowercaseString];
            model.mac = mac;
        }
        
        model.peripheral = peripheral;
        model.advertisementData = advertisementData;
        model.rssi = RSSI.integerValue;
        [_bleArray addObject:model];
        [_bleArray sortUsingComparator:^NSComparisonResult(id  _Nonnull obj1, id  _Nonnull obj2) {
            WKBleModel *model1 = (WKBleModel *)obj1;
            WKBleModel *model2 = (WKBleModel *)obj2;
            return model1.rssi < model2.rssi;
        }];
        [[NSNotificationCenter defaultCenter] postNotificationName:kTag_Phone_Discover_Device object:nil];
    }
    
}

#pragma  mark - 成功连接设备
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {
    
    peripheral.delegate = self;
    [peripheral discoverServices:@[[CBUUID UUIDWithString:ServiceUUID]]];
    [[NSNotificationCenter defaultCenter] postNotificationName:kTag_Device_Connected object:peripheral];
}

#pragma -mark 设备已断开
- (void) centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
    
    [[NSNotificationCenter defaultCenter] postNotificationName:kTag_Device_Disconnected object:peripheral];
}

#pragma mark - CBPeripheralDelegate
#pragma  mark - 接收到已连接设备的服务
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error {
    
    if (error) {
        DLog(@"%s,%@",__func__, error);
    }
    
    for (CBService *service in peripheral.services) {
        [peripheral discoverCharacteristics:nil forService:service];
    }
    
}

#pragma  mark - 获取服务特征
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error {
    if (error) {
        DLog(@"%s,%@",__func__, error);
    }
    
    for (CBCharacteristic *characteristic in service.characteristics) {
        
        [peripheral setNotifyValue:YES forCharacteristic:characteristic];
        
        if ([characteristic.UUID.UUIDString.lowercaseString isEqualToString:NotifyUUID]) {
            _fileService = characteristic;
        }
        else if ([characteristic.UUID.UUIDString.lowercaseString isEqualToString:resetUUID]) {
            _resetService = characteristic;
        }
    }
}

#pragma mark - 写指令
- (void)sendCommand:(NSData *)data toPeripheral:(CBPeripheral *)peripheral {
    [self writeCharacteristic:peripheral sUUID:ServiceUUID cUUID:WriteUUID data:data response:NO];
}

- (void)writeCharacteristic:(CBPeripheral *)peripheral sUUID:(NSString *)sUUID cUUID:(NSString *)cUUID data:(NSData *)data response:(BOOL)response {
    for ( CBService *service in peripheral.services) {
        if ([service.UUID isEqual:[CBUUID UUIDWithString:sUUID]]) {
            for ( CBCharacteristic *characteristic in service.characteristics ) {
                if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:cUUID]]) {
                    if (response) {
                        [peripheral writeValue:data forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse];
                    }
                    else {
                        [peripheral writeValue:data forCharacteristic:characteristic type:CBCharacteristicWriteWithoutResponse];
                    }
                }
            }
        }
    }
}

#pragma mark - 读取返回来的数据
-(void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
    
    DLog(@"蓝牙返回的数据：%@",characteristic.value);
    
    if (error) {
        DLog(@"%s,%@",__func__, error);
    }
    
    int length = (int)characteristic.value.length;
    Byte byte[length];
    [characteristic.value getBytes:byte length:length];
    
    //汉天下升级
    if ([peripheral.name isEqualToString:@"Huntersun-BLE"]) {
        //ISP模式
        if (error) {
            [self.delegete bleNotifyResponseData:nil type:0];
        }
        
        NSMutableData *response = [NSMutableData dataWithData: characteristic.value];
        
        if (characteristic == _fileService){
            [self.delegete bleNotifyResponseData:response type:1];
        }
        else if(characteristic == _resetService){
            [self.delegete bleNotifyResponseData:response type:2];
        }
    }
    
    //正常数据接收
    if (byte[0] == 0xdb && byte[1] == 0x00 && length == 8) {
        self.combineSize = byte[3] + 8 ;
        self.combine = YES;
    }
    
    //开始拼接
    if (self.combine == YES) {
        [self.combineData appendData:characteristic.value];
        //        DLog(@"---------------self.combineData=%@",self.combineData);
        //        DLog(@"---------------self.combineData.length=%lu",(unsigned long)self.combineData.length);
        //        DLog(@"---------------self.combineSize=%d",self.combineSize);
        if (self.combineData.length == self.combineSize) {
            
            Byte combineByte[self.combineSize];
            [self.combineData getBytes:combineByte length:self.combineSize];
            
            //设备返回初始化状态
            if (combineByte[8] == 0x01 && combineByte[10] == 0x02) {
                if (combineByte[13] == 0x01) {
                    DLog(@"已经初始化");
                }
                else if (combineByte[13] == 0x00) {
                    DLog(@"没有初始化");
                }
                [self answer:combineByte[6] andByte7:combineByte[7]];
            }
            
            //设备返回设置密码状态
            if (combineByte[8] == 0x01 && combineByte[10] == 0x04) {
                if (combineByte[13] == 0x01) {
                    DLog(@"密码设置成功");
                }
                else if (combineByte[13] == 0x00) {
                    DLog(@"密码设置失败");
                }
                [self answer:combineByte[6] andByte7:combineByte[7]];
            }
            
            //设备返回设置的密码
            if (combineByte[8] == 0x01 && combineByte[10] == 0x06) {
                NSData *passwordData =[self.combineData subdataWithRange:NSMakeRange(13, self.combineSize-13)];
                NSString *str = [[NSString alloc] initWithData:passwordData encoding:NSUTF8StringEncoding];
                DLog(@"密码=%@",str);
                [self answer:combineByte[6] andByte7:combineByte[7]];
            }
            
            //发送私钥后，获取私钥存储状态
            if (combineByte[8] == 0x02 && combineByte[10] == 0x02) {
                if (combineByte[13] == 0x01) {
                    DLog(@"私钥存储成功");
                }
                else if (combineByte[13] == 0x00) {
                    DLog(@"私钥存储失败");
                }
                [self answer:combineByte[6] andByte7:combineByte[7]];
            }
            
            //获取设备中储存的私钥
            if (combineByte[8] == 0x02 && combineByte[10] == 0x04) {
                NSData *passwordData =[self.combineData subdataWithRange:NSMakeRange(13, self.combineSize-13)];
                NSString *str = [[NSString alloc] initWithData:passwordData encoding:NSUTF8StringEncoding];
                DLog(@"私钥=%@",str);
                [self answer:combineByte[6] andByte7:combineByte[7]];
            }
            
            //拼接完成，重置状态
            self.combine = NO;
            //临时拼接的数组置空
            [self.combineData resetBytesInRange:NSMakeRange(0, self.combineData.length)];
            [self.combineData setLength:0];
        }
    }
    
}

//回应的时候带上包头后两位
- (void)answer:(Byte)byte6 andByte7:(Byte)byte7 {
    Byte byte[8] = {0};
    byte[0] = 0xdb;
    byte[1] = 0x10;
    byte[2] = 0x00;
    byte[3] = 0x00;
    byte[4] = 0x00;
    byte[5] = 0x00;
    byte[6] = byte6;
    byte[7] = byte7;
    NSData *data = [NSData dataWithBytes:byte length:8];
    DLog(@"回复数据=%@",data);
    [bleSelf sendCommand:data toPeripheral:_activePeripheral];
}

#pragma mark - 通讯指令
//查找手环
- (void)sendSeatchBracelet {
    Byte byte[6] = {0};
    byte[0] = 0xab;
    byte[1] = 0;
    byte[2] = 3;
    byte[3] = 0xff;
    byte[4] = 0x71;
    byte[5] = 0x80;
    NSData *data = [NSData dataWithBytes:byte length:6];
    [bleSelf sendCommand:data toPeripheral:_activePeripheral];
}

//获取设备初始化状态
- (void)sendGetDeviceInitStatus {
    Byte byte[11] = {0};
    byte[0] = 0xdb;
    byte[1] = 0x00;
    byte[2] = 0x00;
    byte[3] = 0x03;
    byte[4] = 0x01;
    byte[5] = 0x01;
    byte[6] = 0x00;
    byte[7] = 0x00;
    
    byte[8] = 0x01;
    byte[9] = 0x00;
    byte[10] = 0x01;
    NSData *data = [NSData dataWithBytes:byte length:11];
    [bleSelf sendCommand:data toPeripheral:_activePeripheral];
}

//设置钱包密码
- (void)sendSetDevicePassword:(NSString *)password {
    
    NSData *messageBody = [password dataUsingEncoding:NSUTF8StringEncoding];
    NSUInteger length = messageBody.length;
    
    Byte byte[13] = {0};
    byte[0] = 0xdb;
    byte[1] = 0x00;
    byte[2] = 0x00;
    byte[3] = length + 5;
    byte[4] = 0x01;
    byte[5] = 0x01;
    byte[6] = 0x00;
    byte[7] = 0x00;
    
    byte[8] = 0x01;
    byte[9] = 0x00;
    byte[10] = 0x03;
    byte[11] = 0x00;
    byte[12] = 0x08;
    
    NSData *messageHead = [NSData dataWithBytes:byte length:13];
    NSMutableData *mutableData = [[NSMutableData alloc] init];
    
    [mutableData appendData:messageHead];
    [mutableData appendData:messageBody];
    [bleSelf asunderData:mutableData];
}

//获取钱包密码
- (void)sendGetDevicePassword {
    Byte byte[11] = {0};
    byte[0] = 0xdb;
    byte[1] = 0x00;
    byte[2] = 0x00;
    byte[3] = 0x03;
    byte[4] = 0x01;
    byte[5] = 0x01;
    byte[6] = 0x00;
    byte[7] = 0x00;
    
    byte[8] = 0x01;
    byte[9] = 0x00;
    byte[10] = 0x05;
    NSData *data = [NSData dataWithBytes:byte length:11];
    [bleSelf sendCommand:data toPeripheral:_activePeripheral];
}

//保存钱包秘钥
- (void)sendSavePurseKey:(NSString *)key {
    
    NSData *messageBody = [key dataUsingEncoding:NSUTF8StringEncoding];
    NSUInteger length = messageBody.length;
    
    Byte byte[13] = {0};
    byte[0] = 0xdb;
    byte[1] = 0x00;
    byte[2] = 0x00;
    byte[3] = length + 5;
    byte[4] = 0x01;
    byte[5] = 0x01;
    byte[6] = 0x00;
    byte[7] = 0x00;
    
    byte[8] = 0x02;
    byte[9] = 0x00;
    byte[10] = 0x01;
    byte[11] = 0x00;
    byte[12] = 0x40;
    
    NSData *messageHead = [NSData dataWithBytes:byte length:13];
    NSMutableData *mutableData = [[NSMutableData alloc] init];
    
    [mutableData appendData:messageHead];
    [mutableData appendData:messageBody];
    [bleSelf asunderData:mutableData];
    
}

//获取钱包秘钥
- (void)sendGetPurseKey {
    Byte byte[11] = {0};
    byte[0] = 0xdb;
    byte[1] = 0x00;
    byte[2] = 0x00;
    byte[3] = 0x03;
    byte[4] = 0x01;
    byte[5] = 0x01;
    byte[6] = 0x00;
    byte[7] = 0x00;
    
    byte[8] = 0x02;
    byte[9] = 0x00;
    byte[10] = 0x03;
    NSData *data = [NSData dataWithBytes:byte length:11];
    [bleSelf sendCommand:data toPeripheral:_activePeripheral];
}

//分包
- (void)asunderData:(NSMutableData *)data {
    NSInteger len = data.length;
    int pos = 0;
    int tmp = len % 20;
    NSMutableData *packet_data = [[NSMutableData alloc]initWithLength:20];
    for(int i = 0; i < len / 20; i++){
        packet_data = [bleSelf arrayCopy:data andArray2:packet_data andstart1:pos andlength:20];
        [bleSelf sendCommand:packet_data toPeripheral:_activePeripheral];
        pos = pos + 20;
    }
    if(tmp != 0) {
        NSMutableData *packet_data = [[NSMutableData alloc]initWithLength:tmp];
        packet_data = [bleSelf arrayCopy:data andArray2:packet_data andstart1:pos andlength:tmp];
        [bleSelf sendCommand:packet_data toPeripheral:_activePeripheral];
    }
}

#pragma mark - 固件升级指令
//进入ISP模式
- (void)sendEnterISP {
    Byte byte[7] = {0};
    byte[0] = 0xab;
    byte[1] = 0;
    byte[2] = 4;
    byte[3] = 0xff;
    byte[4] = 0x25;
    byte[5] = 0x80;
    byte[6] = 0x01;
    NSData *data = [NSData dataWithBytes:byte length:7];
    [bleSelf sendCommand:data toPeripheral:_activePeripheral];
}

//发送文件数据
- (int)sendFileData:(NSMutableData*)data len:(int)len {
    int pos = 0;
    int tmp = len % 20;
    NSMutableData *packet_data = [[NSMutableData alloc]initWithLength:20];
    for(int i = 0; i < len / 20; i++){
        packet_data = [bleSelf arrayCopy:data andArray2:packet_data andstart1:pos andlength:20];
        [bleSelf sendCommand:packet_data toPeripheral:_activePeripheral];
        pos = pos + 20;
    }
    if(tmp != 0) {
        NSMutableData *packet_data = [[NSMutableData alloc]initWithLength:tmp];
        packet_data = [bleSelf arrayCopy:data andArray2:packet_data andstart1:pos andlength:tmp];
        [bleSelf sendCommand:packet_data toPeripheral:_activePeripheral];
    }
    return 0;
}

//发送复位数据
- (void)sendCmdData:(NSMutableData *)data {
    int tmp1 = (int)data.length % 20;
    int pos1 = 0;
    if (tmp1 != 0) {
        NSMutableData *packet_data = [[NSMutableData alloc]initWithLength:tmp1];
        packet_data = [bleSelf arrayCopy:data andArray2:packet_data andstart1:pos1 andlength:tmp1];
        [_activePeripheral writeValue:packet_data forCharacteristic:_resetService type:CBCharacteristicWriteWithoutResponse];
    }
}

//数据分包
- (NSMutableData *)arrayCopy:(NSMutableData *)array1 andArray2:(NSMutableData *)array2 andstart1:(int)startindex1 andlength:(int)length {
    
    Byte *byte1 = (Byte *)[array1 bytes];
    Byte *byte2 = (Byte *)[array2 bytes];
    if (byte1 !=nil) {
        for (int i=0; i < length; i++) {
            byte2[i] = byte1[i+startindex1];
        }
    }
    return [[NSMutableData alloc] initWithBytes:byte2 length:array2.length];
}

@end
